/*-----------------------------------------------File Info------------------------------------------------
** File Name:               i2c_user.h
** Last modified date:      2016.07.22
** Last version:            V0.1
** Description:             
**--------------------------------------------------------------------------------------------------------            
** Created date:            2016.09.07
** author:                  YLY
** Version:                 V0.1
** Descriptions:            I2c驱动
**--------------------------------------------------------------------------------------------------------
*/
/* 注意GD32和STM32芯片I2C有硬件设计缺陷，空闲时，只要SCL收到低电平，就无法通讯，此时采用复位I2C看看是否能解决，否则就只有复位MCU */
#ifndef __I2C_USER_H_
#define __I2C_USER_H_
#include "bspConfig.h"
#include "bspGPIO.h"

//#define I2CDEBUG				printf
#ifndef I2CDEBUG
	#define I2CDEBUG(...)		
#endif

#define I2CERR				printf
#ifndef I2CERR
	#define I2CERR(...)		
#endif

//#define I2CINTDBG				printf
#ifndef I2CINTDBG
	#define I2CINTDBG(...)		
#endif

		
#define I2C0_DATA_ADDRESS       (uint32_t)&I2C_DATA(I2C0)	//0x40005410
#define I2C1_DATA_ADDRESS       (uint32_t)&I2C_DATA(I2C1)	//0x40005810


/* 定义i2c从机地址7位地址 0x00-0x7F ,默认使用地址0*/
#define I2C0_SLAVE_ADDR0 			0x3c
#define I2C1_SLAVE_ADDR0 			0x3c	

#define I2C_WDT()					fwdgt_counter_reload()

/* 解决I2C缺陷参数 */

#define I2CBSY_RESET_TIME 			50		//I2C I2C_FLAG_I2CBSY 异常复位时间 50*10mS= 500mS
#define I2CBSY_WAIT_MAX_TIME 		I2CBSY_RESET_TIME+10		//I2C I2C_FLAG_I2CBSY 等待最长时间 60*10mS= 600mS

typedef struct 
{
	rcu_periph_enum rcu;
	uint32_t i2c;
	uint32_t nvicIrqEv;
    uint32_t nvicIrqEvPriority;
	uint32_t nvicIrqEr;
    uint32_t nvicIrqErPriority;
	
	tsCfgGpio sclIo;
	tsCfgGpio sdaIo;
}tsCfgI2c;

/*    I2C0      */
#define DEV_I2C0_0	/* I2C0_A9A10 AF4 */\
		{RCU_I2C0, I2C0, I2C0_EV_IRQn, 2, I2C0_ER_IRQn, 1, /* I2C */\
		RCU_GPIOA, GPIOA, GPIO_PIN_9, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_AF_4,1, /* SCL */\
		RCU_GPIOA, GPIOA, GPIO_PIN_10, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_AF_4,1 /* SDA */}
		
#define DEV_I2C0_1	/* I2C0_B6B7 AF1 */\
		{RCU_I2C0, I2C0, I2C0_EV_IRQn, 2, I2C0_ER_IRQn, 1, /* I2C */\
		RCU_GPIOB, GPIOB, GPIO_PIN_6, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_AF_1,1, /* SCL */\
		RCU_GPIOB, GPIOB, GPIO_PIN_7, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_AF_1,1 /* SDA */}

#define DEV_I2C0_2	/* I2C0_B8B9 AF1 */\
		{RCU_I2C0, I2C0, I2C0_EV_IRQn, 2, I2C0_ER_IRQn, 1, /* I2C */\
		RCU_GPIOB, GPIOB, GPIO_PIN_8, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_AF_1,1, /* SCL */\
		RCU_GPIOB, GPIOB, GPIO_PIN_9, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_AF_1,1 /* SDA */}

#define DEV_I2C0_3	/* I2C0_B10B11 AF1 */\
		{RCU_I2C0, I2C0, I2C0_EV_IRQn, 2, I2C0_ER_IRQn, 1, /* I2C */\
		RCU_GPIOB, GPIOB, GPIO_PIN_10, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_AF_1,1, /* SCL */\
		RCU_GPIOB, GPIOB, GPIO_PIN_11, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_AF_1,1 /* SDA */}

#define DEV_I2C0_4	/* I2C0_F6F7 AF0 */\
		{RCU_I2C0, I2C0, I2C0_EV_IRQn, 2, I2C0_ER_IRQn, 1, /* I2C */\
		RCU_GPIOF, GPIOF, GPIO_PIN_6, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_AF_0,1, /* SCL */\
		RCU_GPIOF, GPIOF, GPIO_PIN_7, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_AF_0,1 /* SDA */}
		
/*    I2C0      */		
#define DEV_I2C1_0	/* I2C1_A0A1 AF4 */\
		{RCU_I2C1, I2C1, I2C1_EV_IRQn, 2, I2C1_ER_IRQn, 1, /* I2C */\
		RCU_GPIOA, GPIOA, GPIO_PIN_0, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_AF_4,1, /* SCL */\
		RCU_GPIOA, GPIOA, GPIO_PIN_1, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_AF_4,1 /* SDA */}

#define DEV_I2C1_1	/* I2C1_A11A12 AF5 */\
		{RCU_I2C1, I2C1, I2C1_EV_IRQn, 2, I2C1_ER_IRQn, 1, /* I2C */\
		RCU_GPIOA, GPIOA, GPIO_PIN_11, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_AF_5,1, /* SCL */\
		RCU_GPIOA, GPIOA, GPIO_PIN_12, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_AF_5,1 /* SDA */}

#define DEV_I2C1_2	/* I2C1_B10B11 AF1 */\
		{RCU_I2C1, I2C1, I2C1_EV_IRQn, 2, I2C1_ER_IRQn, 1, /* I2C */\
		RCU_GPIOB, GPIOB, GPIO_PIN_10, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_AF_1,1, /* SCL */\
		RCU_GPIOB, GPIOB, GPIO_PIN_11, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_AF_1,1 /* SDA */}	

#define DEV_I2C1_3	/* I2C1_B13B14 AF5 */\
		{RCU_I2C1, I2C1, I2C1_EV_IRQn, 2, I2C1_ER_IRQn, 1, /* I2C */\
		RCU_GPIOB, GPIOB, GPIO_PIN_13, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_AF_5,1, /* SCL */\
		RCU_GPIOB, GPIOB, GPIO_PIN_14, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_AF_5,1 /* SDA */}	

#define DEV_I2C1_4	/* I2C1_F1F0 AF1 */\
		{RCU_I2C1, I2C1, I2C1_EV_IRQn, 2, I2C1_ER_IRQn, 1, /* I2C */\
		RCU_GPIOF, GPIOF, GPIO_PIN_1, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_AF_0,1, /* SCL */\
		RCU_GPIOF, GPIOF, GPIO_PIN_0, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_AF_0,1 /* SDA */}	

#define DEV_I2C1_5	/* I2C1_F6F7 AF0 */\
		{RCU_I2C1, I2C1, I2C1_EV_IRQn, 2, I2C1_ER_IRQn, 1, /* I2C */\
		RCU_GPIOF, GPIOF, GPIO_PIN_6, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_AF_0,1, /* SCL */\
		RCU_GPIOF, GPIOF, GPIO_PIN_7, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_AF_0,1 /* SDA */}			

typedef enum eWrOrReMode
{
	I2C_READ,		/* 读 */	
	I2C_WRITE,		/* 写 */	
}teWrOrReMode;

	
typedef enum eMastOrSlave
{
	I2C_SLAVE,		/* 从 */	
	I2C_MAST,		/* 主 */		
}teMastOrSlave;

typedef enum eFeedback
{
	I2C_WAIT=0,		/* 等待 */
	I2C_SUCCESS,	/* 成功	*/	
	I2C_FAIL,		/* 失败 */
	I2C_BUS_ERROR,		/* I2C总线错误 */
}teFeedback;

typedef void (*ptI2C_Callback)(teFeedback feedback, uint8_t *pData, uint16_t size);//状态回调函数
/* 必要时需要增加关键字 volatile */
typedef struct 	strI2c
{
	bool 			intEnSta;			/* 中断使能状态 */
	bool			stopSend;			/* 停止位发送标识 */
	bool			cbSta;				/* 回调状态，防止被多次回调，造成异常*/
	teMastOrSlave  	eMastOrSlave;		/* 主从模式 */	
	teWrOrReMode  	eWrOrRe;			/* 读写模式 */
	uint8_t  		m2sAddr;			/* 主机模式下，从机地址 */
	
	ptI2C_Callback 	tReCb;				/* 反馈回调函数 */
	ptI2C_Callback 	tWrCb;				/* 反馈回调函数 */
	
	uint8_t 		*pRe;				/* 读数据缓冲区 */
	uint8_t 		*pWr;				/* 写数据缓冲区*/	
	uint16_t 		reLen;				/* 读数据长度 */
	uint16_t 		wrLen;				/* 写数据长度  */
	uint16_t 		reCnt;				/* 读数据计数 */
	uint16_t 		wrCnt;				/* 写数据计数  */
}tsI2c;


/* 必要时需要增加关键字 volatile */
typedef struct 	strI2cPara
{
	uint32_t clkRate; 	
	uint8_t addr7Bit;	
}tsI2cPara;


extern void i2cReinit(tsCfgI2c *cfg);	//I2C受到干扰容易出现通讯异常，可重新复位解决。
extern void i2cInit(tsCfgI2c *cfg, uint32_t clkRate, uint8_t addr7Bit)	;

#ifdef I2C_DMA_EN
extern uint8_t i2cDmaMasterWrite(tsCfgI2c *cfg, uint8_t addr, uint8_t *pBuf, uint16_t bufSize, ptI2C_Callback tCb);
extern uint8_t i2cDmaMasterRead(tsCfgI2c *cfg, uint8_t addr, uint8_t *pBuf, uint16_t bufSize, ptI2C_Callback tCb);
#endif

extern uint8_t i2cMasterWrite(tsCfgI2c *cfg, uint8_t addr, uint8_t *pBuf, uint32_t size, ptI2C_Callback tCb);
extern uint8_t i2cMasterRead(tsCfgI2c *cfg, uint8_t addr, uint8_t *pBuf, uint32_t size, ptI2C_Callback tCb);
extern uint8_t i2cSlaveWrite(tsCfgI2c *cfg, uint8_t *pBuf, uint32_t size, ptI2C_Callback tCb);
extern uint8_t i2cSlaveRead(tsCfgI2c *cfg, uint8_t *pBuf, uint32_t size, ptI2C_Callback tCb);
#endif		//__I2C_USER_H_






